﻿using FPSO.HMI.Views.Dialog;
using FPSO.Models.Constant;
using FPSO.Models.Domain;
using FPSO.Services.Impl;
using System;
using System.Collections.Generic;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Threading;
using System.Linq;
using Opc.Ua;
using System.Xml;
using FPSO.HMI.Utils;
using static FPSO.Models.Constant.TankConstant;
using Newtonsoft.Json;
using System.Diagnostics;

namespace FPSO.HMI.Views
{
    /// <summary>
    /// ExecuteView.xaml 的交互逻辑
    /// </summary>
    public partial class ExecuteView : UserControl
    {
        private DispatcherTimer taskTimer;
        private DispatcherTimer updateTaskQueueTimer;

        //simuTaskTimer为临时下发任务的计时器，用于监控任务状态
        //为防止下发任务始终没有达到目标值，计时器无法停止，设置任务执行时间
        private DispatcherTimer simuTaskTimer = null;
        private int simuTaskTick = 0;
        private int maxSimuTaskTick = 180;
        private int simuTaskTimeSpan = 20;

        private DateTime startTime;
        private TaskTankCalcService taskTankCalcService = null;
        private string[] dataFiles = null;
		/// <summary>
		/// 当前状态
		/// </summary>
		Dictionary<string, double> currentVolmDic;

		/// <summary>
		/// m_CurrentCalcResult记录当前根据实采数据（或者模拟数据）计算的舱室及船舶状态
		/// </summary>
		ManualCalcResult m_CurrentCalcResult = new ManualCalcResult();
		public ExecuteView(int showCargo)
        {
            InitializeComponent();

            startTime = DateTime.MinValue;
            taskQueue.TaskService = new DBTankTaskService();
			//在执行界面将任务管理的部分操作控件隐去
			taskQueue.TopOperPanel.Visibility = Visibility.Hidden;
			taskQueue.TaskLoadAdd.Visibility = Visibility.Hidden;
			taskQueue.TaskAutoLoadAdd.Visibility = Visibility.Hidden;
			taskQueue.TaskLoadAdd2.Visibility = Visibility.Hidden;
			taskQueue.TaskUnloadAdd.Visibility = Visibility.Hidden;

			taskTankCalcService = new TaskTankCalcService(taskQueue.TaskService);
			
			taskTimer = new DispatcherTimer();
            taskTimer.Interval = TimeSpan.FromSeconds(1);
            taskTimer.Tick += TaskTimer_Tick;
            taskTimer.Start();

            if (showCargo == 1)
            {
                oilBallast.canvasOil.Visibility = Visibility.Visible;
                oilBallast.canvasOilTank.Visibility = Visibility.Visible;
                oilBallast.canvasBallast.Visibility = Visibility.Hidden;
                oilBallast.canvasBallastTank.Visibility = Visibility.Hidden;
            }
            else if (showCargo == 2)
            {
                oilBallast.canvasOil.Visibility = Visibility.Hidden;
                oilBallast.canvasOilTank.Visibility = Visibility.Hidden;
                oilBallast.canvasBallast.Visibility = Visibility.Visible;
                oilBallast.canvasBallastTank.Visibility = Visibility.Visible;
            }
            else
            {
                oilBallast.canvasOil.Visibility = Visibility.Visible;
                oilBallast.canvasOilTank.Visibility = Visibility.Visible;
                oilBallast.canvasBallast.Visibility = Visibility.Visible;
                oilBallast.canvasBallastTank.Visibility = Visibility.Visible;
            }
			//DEBUG 暂时封掉
			updateTaskQueueTimer = new DispatcherTimer();
			updateTaskQueueTimer.Interval = TimeSpan.FromSeconds(5);
			updateTaskQueueTimer.Tick += TaskQueueTimer_Tick;
			updateTaskQueueTimer.Start();

			// 缓存真实数据获取列表
			//dataFiles = getDataFiles();
		}

		private void TaskQueue_AddTaskAction(object button, int queueId)
        {
            TaskInfoView createView = new TaskInfoView(queueId, new DBTankTaskService());
            try 
			{ 
				createView.ShowDialog();
			} 
			catch (Exception ex)
			{ 
				return;
			}
        }
        /// <summary>
        /// 获取真实数据获取列表
        /// </summary>
        /// <returns></returns>
        static string[] getDataFiles()
        {
            try
            {
                return Directory.GetFiles("D:\\SAFELOAD\\PROJ_708海工自研_FPSO智能液货集成控制系统_20210310\\20231113_数据备份_20231106-1111\\智能装配载数据备份\\Datalog", "log_*");
            }
            catch (Exception)
            {
                return Directory.GetFiles("D:\\DevEnv\\fpso_exe\\Datalog", "log_*");
            }
        }

        protected override void OnRender(DrawingContext drawingContext)
        {
            base.OnRender(drawingContext);
            if (!oilBallast.IsInit())
            {
                oilBallast.StartReal();
            }
			//if (!otherTanksBarlist.IsInitBindingService())
			//{
			//	otherTanksBarlist.StartReal();
			//}
		}

        public void ReloadTaskQueue()
        {
            taskQueue.ControlUpdate();
        }

        /// <summary>
        /// 刷新任务线
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TaskQueueTimer_Tick(object sender, EventArgs e)
        {
            //Dictionary<string, double> currentVolmDic0 = oilBallast.GetTankVolumeDic();
            taskQueue.ControlUpdateByRate(m_CurrentCalcResult);
        }

        private void TaskTimer_Tick(object sender, EventArgs e)
        {
			if (App.UaClient != null)
			{
				UpdateOpcValues_TankStatus(TankConstant.tagList_tankStatus);
				UpdateOpcValues_FlammableGasStatus(TankConstant.tagList_flammableGasStatus);
				UpdateOpcValues_ValveStatus(TankConstant.tagList_valveStatus);
				UpdateOpcValues_PumpStatus(TankConstant.tagList_pumpStatus);
				UpdateOpcValues_HardwireStatus(TankConstant.tagList_hardwireStatus);
			}

			//待测试
			oilBallast.SetImitateTime(DateTime.Now);

			//DEBUG 暂时封掉右下角其他液舱的数据
			//otherTanksBarlist.ReflushUIValues(DateTime.Now);

			taskQueue.CurrentTime = DateTime.Now;

			//先获取一次状态，再刷新当前舱室状态
			currentVolmDic = oilBallast.GetTankVolumeDic();
			SafeLoadAlgorithmService algorithmService = SafeLoadAlgorithmService.GetInstance();
			m_CurrentCalcResult = algorithmService.CallManualCalc(currentVolmDic, 3);
		}

		private void oilBallast_OnAddTankTask(string srcTankId)
        {
			if (!AuthUtil.IsHasPermission())
			{
				return;
			}
			TankLoadTypeSelectDialog tankLoadTypeSelectDialog = new TankLoadTypeSelectDialog();
            if (tankLoadTypeSelectDialog.ShowDialog() == true)
            {
                if (tankLoadTypeSelectDialog.LoadTypeSelect == 1)
                {
                    //DEBUG 这里仿照压载倒舱，点击可制定货油注入任务，原先制定计划的过程暂时封掉
                    Dictionary<string, double> currentVolmDic0 = oilBallast.GetTankVolumeDic();
                    COTLoadTaskDialog loadTaskDialog = new COTLoadTaskDialog(srcTankId, currentVolmDic0, false);
                    if (loadTaskDialog.ShowDialog() == true)
                    {
                        List<ConstantTankInfo> taskInfos = TankConstant.getCOTTank();
                        Dictionary<string, double> taskTankVolume = currentVolmDic0;
                        string tar_tankName = loadTaskDialog.g_TargetTank;
                        double adjustvol = loadTaskDialog.g_Adjustvol;
                        Int16 srctankno = 0;
                        for (int i = 0; i < taskInfos.Count; i++)
                        {
                            ConstantTankInfo info = taskInfos[i];
                            string tankname = info.TankName;
                            if (tankname == srcTankId)
                            {
                                string tankId = info.TankID;
                                taskTankVolume[tankId] += adjustvol;
                                srctankno = Convert.ToInt16(i + 1);
                                break;
                            }
                        }
                        SafeLoadAlgorithmService algorithmService = SafeLoadAlgorithmService.GetInstance();
                        ManualCalcResult calcResult = algorithmService.CallManualCalc(taskTankVolume, 3);
                        if (calcResult.GetShipCheckStatus() == true)
                        {
                            //再次确认
                            var dialgoResult = MessageBox.Show("完成货油注入任务下发前检查，是否继续?", "提示", MessageBoxButton.YesNo);
                            if (dialgoResult == MessageBoxResult.Yes)
                            {
                                double srctanklevel = calcResult.GetTankCalcStateByName(srcTankId).Inn;
                                Int16 readflag = 2;
                                Int16 tanktype = 0;
                                Int16 taskop = 1;

                                string taskpre = "Task1CTInstructCache[0]";
                                string tag0 = "ReadFlag";
                                string tag1 = "sourceTkNo";
                                string tag2 = "targetTkNo";
                                string tag3 = "TkType";
                                string tag4 = "TargetLevel";
                                string tag5 = "TaskOp";
                                string tag6 = "TargetLevelIdx";

                                string tag_start = "HmiTask1CTInstructStartCmd";
                                string status_tag0 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag0);
                                string status_tag1 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag1);
                                string status_tag2 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag2);
                                string status_tag3 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag3);
                                string status_tag4 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag4);
                                string status_tag5 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag5);
                                string status_tag6 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag6);
                                string status_tag_start = string.Format("{0}{1}", SysConfig.OPC_ADD_PRE, tag_start);

                                //注入没有原舱，代码以0代替
								try
								{
									App.UaClient.WriteNode<Int16>(status_tag1, 0);
									App.UaClient.WriteNode<Int16>(status_tag2, srctankno);
									App.UaClient.WriteNode<Int16>(status_tag3, tanktype);
									App.UaClient.WriteNode<float>(status_tag4, Convert.ToSingle(srctanklevel));

									//[实船调试] 在下面一句设断点，逐步调试，看能否正确发出数据
									App.UaClient.WriteNode<Int16>(status_tag5, taskop);
									Int16 targetLevelIdx = TankConstant.g_TargetCotLevelIdx[srctankno - 1];
									App.UaClient.WriteNode<Int16>(status_tag6, targetLevelIdx);
									dialgoResult = MessageBox.Show("完成货油注入任务下发，是否确认执行?", "提示", MessageBoxButton.YesNo);
									if (dialgoResult == MessageBoxResult.Yes)
									{
										App.UaClient.WriteNode<Int16>(status_tag0, readflag);
										App.UaClient.WriteNode<Boolean>(status_tag_start, true);

										string info = string.Format("装载舱室：[{0}] 目标液位[{1:N3}]M", srcTankId, srctanklevel);
										CommUtil.AddSystemLog(6, 0, info);
										simuTaskTimer = new DispatcherTimer();
										simuTaskTimer.Interval = TimeSpan.FromSeconds(simuTaskTimeSpan);
										simuTaskTimer.Tick += SimuTaskTimer_Tick1;
										simuTaskTimer.Tag = string.Format("{0}:{1:N3}", srcTankId, srctanklevel);
										simuTaskTick = 0;
										simuTaskTimer.Start();
									}
								}
								catch(Exception ex)
								{
									CommUtil.AddSystemLog(0, 2, ex.Message);
									return;
								}
                            }
                        }
                    }
                }
                else if (tankLoadTypeSelectDialog.LoadTypeSelect == 2)
                {
                    //DEBUG 双击主界面设置舱室调载目标的交互暂时封掉
                    Dictionary<string, double> currentVolmDic0 = oilBallast.GetTankVolumeDic();
                    Dictionary<string, double> currentLevelDic0 = oilBallast.GetTankInnDic();
                    WBTSwapTaskDialog wBTSwapTaskDialog = new WBTSwapTaskDialog(srcTankId, currentVolmDic0, currentLevelDic0, false);
                    if (wBTSwapTaskDialog.ShowDialog() == true)
                    {
                        List<ConstantTankInfo> taskInfos = TankConstant.getCOTTank();
                        Dictionary<string, double> taskTankVolume = currentVolmDic0;
                        string tar_tankName = wBTSwapTaskDialog.g_TargetTank;
                        double adjustvol = wBTSwapTaskDialog.g_Adjustvol;
                        bool heelChecked = wBTSwapTaskDialog.g_HeelChecked;
                        Int16 srctankno = 0;
                        Int16 tartankno = 0;
                        for (int i = 0; i < taskInfos.Count; i++)
                        {
                            ConstantTankInfo info = taskInfos[i];
                            string tankname = info.TankName;
                            if (tankname == srcTankId)
                            {
                                string tankId = info.TankID;
                                taskTankVolume[tankId] -= adjustvol;
                                srctankno = Convert.ToInt16(i + 1);
                            }
                            else if (tankname == tar_tankName)
                            {
                                string tankId = info.TankID;
                                taskTankVolume[tankId] += adjustvol;
                                tartankno = Convert.ToInt16(i + 1);
                            }
                        }

                        SafeLoadAlgorithmService algorithmService = SafeLoadAlgorithmService.GetInstance();
                        ManualCalcResult calcResult = algorithmService.CallManualCalc(taskTankVolume, 3);
                        if (calcResult.GetShipCheckStatus() == true)
                        {
                            //再次确认
                            var dialgoResult = MessageBox.Show("完成倒舱任务下发前检查，是否继续?", "提示", MessageBoxButton.YesNo);
                            if (dialgoResult == MessageBoxResult.Yes)
                            {
                                double srctanklevel = calcResult.GetTankCalcStateByName(srcTankId).Inn;
                                double tartanklevel = calcResult.GetTankCalcStateByName(tar_tankName).Inn;
                                Int16 readflag = 2;
                                Int16 tanktype = 0;
                                Int16 taskop = 3;

                                string taskpre = "Task3CTInstructCache[0]";
                                string tag0 = "ReadFlag";
                                string tag1 = "sourceTkNo";
                                string tag2 = "targetTkNo";
                                string tag3 = "TkType";
                                string tag4 = "TargetLevel";
                                string tag5 = "TaskOp";
                                string tag6 = "TargetLevelIdx";

                                string tag_start = "HmiTask3CTInstructStartCmd";
                                string status_tag0 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag0);
                                string status_tag1 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag1);
                                string status_tag2 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag2);
                                string status_tag3 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag3);
                                string status_tag4 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag4);
                                string status_tag5 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag5);
                                string status_tag6 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag6);
                                string status_tag_start = string.Format("{0}{1}", SysConfig.OPC_ADD_PRE, tag_start);

								try
								{
									App.UaClient.WriteNode<Int16>(status_tag1, srctankno);
									App.UaClient.WriteNode<Int16>(status_tag2, tartankno);
									App.UaClient.WriteNode<Int16>(status_tag3, tanktype);
									App.UaClient.WriteNode<float>(status_tag4, Convert.ToSingle(srctanklevel));
									//App.UaClient.WriteNode<float>(status_tag4, Convert.ToSingle(tartanklevel));
									App.UaClient.WriteNode<Int16>(status_tag5, taskop);
									Int16 targetLevelIdx = TankConstant.g_TargetCotLevelIdx[srctankno - 1];
									App.UaClient.WriteNode<Int16>(status_tag6, targetLevelIdx);

									dialgoResult = MessageBox.Show("完成倒舱任务下发，是否确认执行?", "提示", MessageBoxButton.YesNo);
									if (dialgoResult == MessageBoxResult.Yes)
									{
										App.UaClient.WriteNode<Int16>(status_tag0, readflag);
										App.UaClient.WriteNode<Boolean>(status_tag_start, true);

										simuTaskTimer = new DispatcherTimer();
										simuTaskTimer.Interval = TimeSpan.FromSeconds(simuTaskTimeSpan);
										simuTaskTimer.Tick += SimuTaskTimer_Tick1;
										if (heelChecked)
										{
											ShipDraught realDraught = shipInfo.GetRealShipInfo();
											double Dm_ps = realDraught.MidPDraft;
											double Dm_sb = realDraught.MidSDraft;
											string info = string.Format("装载舱室：[{0}] 当前液位[{1:N3}]M，当前舯左吃水[{2:N3}]M，当前舯右吃水[{3:N3}]M",
												tar_tankName, tartanklevel, Dm_ps, Dm_sb);
											CommUtil.AddSystemLog(6, 1, info);
											simuTaskTimer.Tag = string.Format("Draft:{0}:{1:N3}", tar_tankName, tartanklevel);
										}
										else
										{
											string info = string.Format("排载舱室：[{0}] 目标液位[{1:N3}]M，压载舱室：[{2}] 目标液位[{3:N3}]M",
											srcTankId, srctanklevel, tar_tankName, tartanklevel);
											CommUtil.AddSystemLog(6, 0, info);
											simuTaskTimer.Tag = string.Format("{0}:{1:N3}", tar_tankName, tartanklevel);
										}
										simuTaskTick = 0;
										simuTaskTimer.Start();
										return;
									}
								}
								catch (Exception ex)
								{
									CommUtil.AddSystemLog(0, 2, ex.Message);
									return;
								}
                            }
                        }
                    }
                }
            }
        }
        private void oilBallast_OnAddBwtTankTask(string srcTankId)
        {
            TankLoadTypeSelectDialog tankLoadTypeSelectDialog = new TankLoadTypeSelectDialog();
            if (tankLoadTypeSelectDialog.ShowDialog() == true)
            {
                if (tankLoadTypeSelectDialog.LoadTypeSelect == 2)
                {
                    //DEBUG 双击主界面设置舱室调载目标的交互暂时封掉
                    Dictionary<string, double> currentVolmDic0 = oilBallast.GetTankVolumeDic();
                    Dictionary<string, double> currentLevelDic0 = oilBallast.GetTankInnDic();
                    WBTSwapTaskDialog wBTSwapTaskDialog = new WBTSwapTaskDialog(srcTankId, currentVolmDic0, currentLevelDic0, true);
                    if (wBTSwapTaskDialog.ShowDialog() == true)
                    {
                        List<ConstantTankInfo> taskInfos = TankConstant.getWBTTank();
                        Dictionary<string, double> taskTankVolume = currentVolmDic0;
                        string tar_tankName = wBTSwapTaskDialog.g_TargetTank;
                        double adjustvol = wBTSwapTaskDialog.g_Adjustvol;
                        bool heelChecked = wBTSwapTaskDialog.g_HeelChecked;
                        Int16 srctankno = 0;
                        Int16 tartankno = 0;
                        for (int i = 0; i < taskInfos.Count; i++)
                        {
                            ConstantTankInfo info = taskInfos[i];
                            string tankname = info.TankName;
                            if (tankname == srcTankId)
                            {
                                string tankId = info.TankID;
                                taskTankVolume[tankId] -= adjustvol;
                                srctankno = Convert.ToInt16(i + 1);
                            }
                            else if (tankname == tar_tankName)
                            {
                                string tankId = info.TankID;
                                taskTankVolume[tankId] += adjustvol;
                                tartankno = Convert.ToInt16(i + 1);
                            }
                        }

                        SafeLoadAlgorithmService algorithmService = SafeLoadAlgorithmService.GetInstance();
                        ManualCalcResult calcResult = algorithmService.CallManualCalc(taskTankVolume, 3);
                        if (calcResult.GetShipCheckStatus() == true)
                        {
                            //再次确认
                            var dialgoResult = MessageBox.Show("完成倒舱任务下发前检查，是否继续?", "提示", MessageBoxButton.YesNo);
                            if (dialgoResult == MessageBoxResult.Yes)
                            {
                                double srctanklevel = calcResult.GetTankCalcStateByName(srcTankId).Inn;
                                double tartanklevel = calcResult.GetTankCalcStateByName(tar_tankName).Inn;
                                Int16 readflag = 2;
                                Int16 tanktype = 1;
                                Int16 taskop = 3;

                                string taskpre = "Task3BTInstructCache[0]";
                                string tag0 = "ReadFlag";
                                string tag1 = "sourceTkNo";
                                string tag2 = "targetTkNo";
                                string tag3 = "TkType";
                                string tag4 = "TargetLevel";
                                string tag5 = "TaskOp";
                                string tag6 = "TargetLevelIdx";

                                string tag_start = "HmiTask3BTInstructStartCmd";
                                string status_tag0 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag0);
                                string status_tag1 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag1);
                                string status_tag2 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag2);
                                string status_tag3 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag3);
                                string status_tag4 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag4);
                                string status_tag5 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag5);
                                string status_tag6 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag6);
                                string status_tag_start = string.Format("{0}{1}", SysConfig.OPC_ADD_PRE, tag_start);

								try
								{
									App.UaClient.WriteNode<Int16>(status_tag1, srctankno);
									App.UaClient.WriteNode<Int16>(status_tag2, tartankno);
									App.UaClient.WriteNode<Int16>(status_tag3, tanktype);
									App.UaClient.WriteNode<float>(status_tag4, Convert.ToSingle(srctanklevel));
									//App.UaClient.WriteNode<float>(status_tag4, Convert.ToSingle(tartanklevel));
									App.UaClient.WriteNode<Int16>(status_tag5, taskop);
									Int16 targetLevelIdx = TankConstant.g_TargetBwtLevelIdx[srctankno - 1];
									App.UaClient.WriteNode<Int16>(status_tag6, targetLevelIdx);

									dialgoResult = MessageBox.Show("完成倒舱任务下发，是否确认执行?", "提示", MessageBoxButton.YesNo);
									if (dialgoResult == MessageBoxResult.Yes)
									{
										App.UaClient.WriteNode<Int16>(status_tag0, readflag);
										App.UaClient.WriteNode<Boolean>(status_tag_start, true);

										simuTaskTimer = new DispatcherTimer();
										simuTaskTimer.Interval = TimeSpan.FromSeconds(simuTaskTimeSpan);
										simuTaskTimer.Tick += SimuTaskTimer_Tick1;
										if (heelChecked)
										{
											ShipDraught realDraught = shipInfo.GetRealShipInfo();
											double Dm_ps = realDraught.MidPDraft;
											double Dm_sb = realDraught.MidSDraft;
											string info = string.Format("装载舱室：[{0}] 当前液位[{1:N3}]M，当前舯左吃水[{2:N3}]M，当前舯右吃水[{3:N3}]M",
												tar_tankName, tartanklevel, Dm_ps, Dm_sb);
											CommUtil.AddSystemLog(6, 1, info);
											simuTaskTimer.Tag = string.Format("Draft:{0}:{1:N3}", tar_tankName, tartanklevel);
										}
										else
										{
											string info = string.Format("排载舱室：[{0}] 目标液位[{1:N3}]M，压载舱室：[{2}] 目标液位[{3:N3}]M",
											srcTankId, srctanklevel, tar_tankName, tartanklevel);
											CommUtil.AddSystemLog(6, 0, info);
											simuTaskTimer.Tag = string.Format("{0}:{1:N3}", tar_tankName, tartanklevel);
										}
										simuTaskTick = 0;
										simuTaskTimer.Start();
										return;
									}
								}
								catch (Exception ex)
								{
									CommUtil.AddSystemLog(0, 2, ex.Message);
									return;
								}
                            }
                        }
                    }
                }
                else if (tankLoadTypeSelectDialog.LoadTypeSelect == 1)
                {
                    //DEBUG 这里仿照压载倒舱，点击可制定货油注入任务，原先制定计划的过程暂时封掉
                    Dictionary<string, double> currentVolmDic0 = oilBallast.GetTankVolumeDic();
                    COTLoadTaskDialog loadTaskDialog = new COTLoadTaskDialog(srcTankId, currentVolmDic0, true);
                    if (loadTaskDialog.ShowDialog() == true)
                    {
                        List<ConstantTankInfo> taskInfos = TankConstant.getWBTTank();
                        Dictionary<string, double> taskTankVolume = currentVolmDic0;
                        string tar_tankName = loadTaskDialog.g_TargetTank;
                        double adjustvol = loadTaskDialog.g_Adjustvol;
                        int loadType = loadTaskDialog.g_LoadType;
                        if (loadType == 2)
                            adjustvol = -adjustvol;
                        Int16 srctankno = 0;
                        for (int i = 0; i < taskInfos.Count; i++)
                        {
                            ConstantTankInfo info = taskInfos[i];
                            string tankname = info.TankName;
                            if (tankname == srcTankId)
                            {
                                string tankId = info.TankID;
                                taskTankVolume[tankId] += adjustvol;
                                srctankno = Convert.ToInt16(i + 1);
                                break;
                            }
                        }
                        SafeLoadAlgorithmService algorithmService = SafeLoadAlgorithmService.GetInstance();
                        ManualCalcResult calcResult = algorithmService.CallManualCalc(taskTankVolume, 3);
                        if (calcResult.GetShipCheckStatus() == true)
                        {
                            //再次确认
                            var dialgoResult = MessageBox.Show("完成压载任务下发前检查，是否继续?", "提示", MessageBoxButton.YesNo);
                            if (dialgoResult == MessageBoxResult.Yes)
                            {
                                double srctanklevel = calcResult.GetTankCalcStateByName(srcTankId).Inn;
                                Int16 readflag = 2;
                                Int16 tanktype = 1;
                                Int16 taskop = Convert.ToInt16(loadType);

                                string taskpre = "Task1BTInstructCache[0]";
                                string tag0 = "ReadFlag";
                                string tag1 = "sourceTkNo";
                                string tag2 = "targetTkNo";
                                string tag3 = "TkType";
                                string tag4 = "TargetLevel";
                                string tag5 = "TaskOp";
                                string tag6 = "TargetLevelIdx";

                                string tag_start = "HmiTask1BTInstructStartCmd";
                                string status_tag0 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag0);
                                string status_tag1 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag1);
                                string status_tag2 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag2);
                                string status_tag3 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag3);
                                string status_tag4 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag4);
                                string status_tag5 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag5);
                                string status_tag6 = string.Format("{0}{1}.{2}", SysConfig.OPC_ADD_PRE, taskpre, tag6);
                                string status_tag_start = string.Format("{0}{1}", SysConfig.OPC_ADD_PRE, tag_start);

                                //注入没有原舱，代码以0代替
                                //排载过程，舱室编号下发至sourceTkNo；tag1
                                //压载过程，舱室编号下发至targetTkNo。tag2
								try
								{
									if (loadType == 2)
									{
										App.UaClient.WriteNode<Int16>(status_tag1, srctankno);
										App.UaClient.WriteNode<Int16>(status_tag2, 0);
									}
									else
									{
										App.UaClient.WriteNode<Int16>(status_tag1, 0);
										App.UaClient.WriteNode<Int16>(status_tag2, srctankno);
									}

									App.UaClient.WriteNode<Int16>(status_tag3, tanktype);
									//App.UaClient.WriteNode<float>(status_tag4, Convert.ToSingle(srctanklevel));
									App.UaClient.WriteNode<float>(status_tag4, Convert.ToSingle(srctanklevel));
									App.UaClient.WriteNode<Int16>(status_tag5, taskop);

									Int16 targetLevelIdx = TankConstant.g_TargetBwtLevelIdx[srctankno - 1];
									App.UaClient.WriteNode<Int16>(status_tag6, targetLevelIdx);

									dialgoResult = MessageBox.Show("完成压载任务下发，是否确认执行?", "提示", MessageBoxButton.YesNo);
									if (dialgoResult == MessageBoxResult.Yes)
									{
										App.UaClient.WriteNode<Int16>(status_tag0, readflag);
										App.UaClient.WriteNode<Boolean>(status_tag_start, true);

										string info = string.Format("装载舱室：[{0}] 目标液位[{1:N3}]M", srcTankId, srctanklevel);
										CommUtil.AddSystemLog(6, 0, info);
										simuTaskTimer = new DispatcherTimer();
										simuTaskTimer.Interval = TimeSpan.FromSeconds(simuTaskTimeSpan);
										simuTaskTimer.Tick += SimuTaskTimer_Tick1;
										simuTaskTimer.Tag = string.Format("{0}:{1:N3}", srcTankId, srctanklevel);
										simuTaskTick = 0;
										simuTaskTimer.Start();
									}
								}
								catch (Exception ex)
								{
									CommUtil.AddSystemLog(0, 2, ex.Message);
									return;
								}
                            }
                        }
                    }
                }
            }
        }
        private void SimuTaskTimer_Tick1(object sender, EventArgs e)
        {
            string tag = Convert.ToString(simuTaskTimer.Tag);
            Dictionary<string, double> currentVolmDic0 = oilBallast.GetTankVolumeDic();
            SafeLoadAlgorithmService algorithmService = SafeLoadAlgorithmService.GetInstance();
            ManualCalcResult calcResult = algorithmService.CallManualCalc(currentVolmDic0, 3);

            bool check = true;
            if (tag.Contains("DRAFT"))
            {
                string tar_tankname = tag.Split(':')[1];
                double tar_tanklevel = Convert.ToDouble(tag.Split(':')[1]);
                ShipDraught realDraught = shipInfo.GetRealShipInfo();
                double Dm_ps = realDraught.MidPDraft;
                double Dm_sb = realDraught.MidSDraft;
                string info = string.Format("装载舱室：[{0}] 当前液位[{1:N3}]M，当前舯左吃水[{2:N3}]M，当前舯右吃水[{3:N3}]M",
                    tar_tankname, tar_tanklevel, Dm_ps, Dm_sb);
                CommUtil.AddSystemLog(6, 1, info);

                bool stop_check = false;
                //如果两舯吃水差小于10cm，则返回
                if (Math.Abs(Dm_ps - Dm_sb) < 0.1)
                {
                    check = false;
                    stop_check = true;
                }
                //很可能采集值波动较大，始终无法落在上条件区间，则通过调载方向判定
                else
                {
                    //如果目标舱是左舱，则右排载左压载，原状态为右倾，至左倾时返回
                    //如果目标舱是右舱，则左排载右压载，原状态为左倾，至右倾时返回
                    if ((tar_tankname.Contains("P") && (Dm_ps - Dm_sb > 0.1))
                        || (tar_tankname.Contains("S") && (Dm_sb - Dm_ps > 0.1)))
                    {
                        check = false;
                        stop_check = true;
                    }
                }
                if (stop_check)
                {
                    //string tag_stop = "HMITaskStopCmd";
                    string tag_stop = "TskInstructResetOp";
                    string status_tag0 = string.Format("{0}{1}", SysConfig.OPC_ADD_PRE, tag_stop);
                    App.UaClient.WriteNode<Boolean>(status_tag0, true);
                    CommUtil.AddSystemLog(6, 0, "调载完成");
                    simuTaskTimer.Stop();
                }
            }
            else
            {
                string tar_tankname = tag.Split(':')[0];
                double tar_tanklevel = Convert.ToDouble(tag.Split(':')[1]);
                double cur_tanklevel = calcResult.GetTankCalcStateByName(tar_tankname).Inn;
                string info = string.Format("装载舱室：[{0}] 目标液位[{1:N3}]M，当前液位[{2:N3}]M",
                    tar_tankname, tar_tanklevel, cur_tanklevel);
                CommUtil.AddSystemLog(6, 0, info);

                if (cur_tanklevel >= tar_tanklevel)
                {
                    check = false;
                    CommUtil.AddSystemLog(6, 0, "调载完成");
                }
            }
            simuTaskTick++;
            if (simuTaskTick > maxSimuTaskTick)
                check = false;

            if (!check)
            {
                //此处需要向下位机发送终止当前过程的命令
                //string tag_stop = "HMITaskStopCmd";
                //string status_tag0 = string.Format("{0}{1}", SysConfig.OPC_ADD_PRE, tag_stop);
                //App.UaClient.WriteNode<Boolean>(status_tag0, true);
                simuTaskTimer.Stop();
            }
        }
        public void SetShipDraught(ShipDraught calcDraught, ShipDraught realDraught)
        {
            shipInfo.SetShipInfo(calcDraught, realDraught);
        }
        public void SetTankStatus(ManualCalcResult calcResult)
        {
            oilBallast.SetTankStatus(calcResult);
            //otherTanksBarlist.SetTankStatus(calcResult);
        }

        //以下部分都是主界面用于模拟的程序
        //舱室监控曲线窗口
        private TankMonitorDialog tankMonitorDialogInstance;
        //实船吃水对比曲线窗口
        private RealDataMonitorDialog realDataMonitorDialogInstance;

        /// <summary>
        /// 打开舱室监控曲线图
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TankMonitorButton_Click(object sender, RoutedEventArgs e)
        {
            if (tankMonitorDialogInstance == null || !tankMonitorDialogInstance.IsVisible)
            {
                tankMonitorDialogInstance = new TankMonitorDialog();
                tankMonitorDialogInstance.Closed += TankMonitorDialogClosed;
                tankMonitorDialogInstance.Show();
            }
            else
            {
                // 如果窗口已经可见，可以选择将其激活
                tankMonitorDialogInstance.Activate();
            }
        }
        private void TankMonitorDialogClosed(object sender, EventArgs e)
        {
            // 窗口关闭时，将实例设置为 null，以便可以再次创建
            tankMonitorDialogInstance = null;
        }

        /// <summary>
        /// 打开实船吃水对比曲线图
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void RealDataTestButton_Click(object sender, RoutedEventArgs e)
        {
            if (realDataMonitorDialogInstance == null || !realDataMonitorDialogInstance.IsVisible)
            {
                realDataMonitorDialogInstance = new RealDataMonitorDialog();
                realDataMonitorDialogInstance.Closed += RealDataMonitorDialogClosed;
                realDataMonitorDialogInstance.Show();
            }
            else
            {
                realDataMonitorDialogInstance.Activate();
            }
        }
        private void RealDataMonitorDialogClosed(object sender, EventArgs e)
        {
            realDataMonitorDialogInstance = null;
        }

		//以下是用于离线环境模拟自动注入决策、自动执行的程序，模拟过程可参见脚本
		private List<OpcTask> taskList = new List<OpcTask>();
        /// <summary>
        /// 舱室列表
        /// </summary>
        private List<string> simuTankList = new List<string>();
        /// <summary>
        /// 液位高
        /// </summary>
        private List<double> simuTankLevelList = new List<double>();
        /// <summary>
        /// 装卸状态0不动1装-1卸
        /// </summary>
        private List<int> simuTankStatusList = new List<int>();
        /// <summary>
        /// 设备状态
        /// </summary>
        private List<List<string>> simuTankValvesList = new List<List<string>>();

        private OPCUtil opcUtil = new OPCUtil();

		/// <summary>
		/// OnGoing = 0，停止；OnGoing = 1，在执行；OnGoing = 2，暂停
		/// </summary>
		private int OnGoing = 0;

        /// <summary>
        /// 任务列表
        /// </summary>
        private List<TankTask> simuTaskList = new List<TankTask>();
		DispatcherTimer CurrentVolmTimer = null;

		/// <summary>
		/// 启动实时方案推送
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void BeginRealTimeTaskPushButton_Click(object sender, RoutedEventArgs e)
		{
			if (OnGoing == 0)
			{
				simuTaskList.Clear();
				simuTankList.Clear();
				simuTankLevelList.Clear();
				simuTankStatusList.Clear();
				simuTankValvesList.Clear();
				//建立任务列表
				GetTaskList();
				//开始数据模拟任务
				SimuTaskBegin();
				//开启计时器每秒自动刷新
				CurrentVolmTimer = new DispatcherTimer();
				CurrentVolmTimer.Interval = TimeSpan.FromSeconds(5);
				CurrentVolmTimer.Tick += RefrushCurrentVolmDic1;
				CurrentVolmTimer.Start();
				OnGoing = 1;
			}
			else if (OnGoing == 2)
			{
				CurrentVolmTimer.Start();
				OnGoing = 1;
			}
			BeginRealTimeTaskPushButton.Background = new SolidColorBrush(Colors.Green);
		}

		private void BeginRealTimeTaskPauseButton_Click(object sender, RoutedEventArgs e)
		{
			if (OnGoing == 1)
			{
				CurrentVolmTimer.Stop();
				BeginRealTimeTaskPushButton.Background = new SolidColorBrush(Colors.Orange);
				OnGoing = 2;
			}
			else if (OnGoing == 2)
			{
				BeginRealTimeTaskPushButton.Background = new SolidColorBrush(Colors.Transparent);
				OnGoing = 0;
			}
		}

		/// <summary>
		/// 每秒刷新一次状态
		/// </summary>
		/// <param name="source"></param>
		/// <param name="e"></param>
		private void RefrushCurrentVolmDic1(object sender, EventArgs e)
		{
			SimuTaskBegin();
			Console.WriteLine("刷新一次状态");
		}

		/// <summary>
		/// 数据模拟按钮事件
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void SimuDataTestButton_Click(object sender, RoutedEventArgs e)
        {
			string processName = "SharpNodeSettings.OpcUaServer";
			Process[] processes = Process.GetProcesses(".");
			bool server_exist = false;
			foreach(Process process in processes)
			{
				string name = process.ProcessName;
				if(name.IndexOf("OpcUaServer") > -1)
				{
					server_exist = true;
					break;
				}
			}
			if(server_exist == false)
			{
				CommUtil.AddSystemLog(3, 3, processName);
				return;
			}

			if (OnGoing == 0)
			{
				simuTaskList.Clear();
				simuTankList.Clear();
				simuTankLevelList.Clear();
				simuTankStatusList.Clear();
				simuTankValvesList.Clear();
				//建立任务列表
				GetTaskList();
				//开始数据模拟任务
				SimuTaskBegin1();
				//开启计时器每秒自动刷新
				CurrentVolmTimer = new DispatcherTimer();
				CurrentVolmTimer.Interval = TimeSpan.FromSeconds(1);
				CurrentVolmTimer.Tick += RefrushCurrentVolmDic;
				CurrentVolmTimer.Start();
				OnGoing = 1;
			}
			else if(OnGoing == 2)
			{
				CurrentVolmTimer.Start();
				OnGoing = 1;
			}
			SimuDataTestButton.Background = new SolidColorBrush(Colors.Green);
		}

		private void SimuDataTestPauseButton_Click(object sender, RoutedEventArgs e)
		{
			if (OnGoing == 1)
			{
				CurrentVolmTimer.Stop();
				SimuDataTestButton.Background = new SolidColorBrush(Colors.Orange);
				OnGoing = 2;
			}
			else if(OnGoing == 2)
			{
				SimuDataTestButton.Background = new SolidColorBrush(Colors.Transparent);
				OnGoing = 0;
			}
		}

		private void GetTaskList()
		{
			if (taskList.Count() > 0)
				return;

			try
			{
				XmlDocument xml = new XmlDocument();
				xml.Load("./opctask.xml");
				XmlNodeList nodeList = xml.SelectNodes("/Tasks/Task");
				foreach (XmlNode task in nodeList)
				{
					OpcTask opcTask = new OpcTask();
					opcTask.TaskName = task.Attributes["Name"].Value;
					opcTask.TagList = new List<OPCTag>();
					foreach (XmlNode tag in task.ChildNodes)
					{
						string opcType = tag.Attributes["OpcType"].Value.Trim().ToLower();
						string opcValue = tag.Attributes["Value"].Value.Trim();

						OPCTag opcTag = new OPCTag();
						opcTag.OpcName = tag.Attributes["OPCTag"].Value.Trim();
						opcTag.OpcType = opcType;
						opcTag.OpcValue = new DataValue();

						switch (opcType)
						{
							case "byte": opcTag.OpcValue.Value = Convert.ToByte(opcValue); break;
							case "sbyte": opcTag.OpcValue.Value = Convert.ToSByte(opcValue); break;
							case "short": opcTag.OpcValue.Value = Convert.ToInt16(opcValue); break;
							case "ushort": opcTag.OpcValue.Value = Convert.ToUInt16(opcValue); break;
							case "int": opcTag.OpcValue.Value = Convert.ToInt32(opcValue); break;
							case "uint": opcTag.OpcValue.Value = Convert.ToUInt32(opcValue); break;
							case "long": opcTag.OpcValue.Value = Convert.ToInt64(opcValue); break;
							case "ulong": opcTag.OpcValue.Value = Convert.ToUInt64(opcValue); break;
							case "real": opcTag.OpcValue.Value = Convert.ToSingle(opcValue); break;
							case "bin":
								{
									opcTag.OpcValue.Value = opcValue.PadLeft(16, '0');
									break;
								}
						}
						opcTask.TagList.Add(opcTag);
					}
					taskList.Add(opcTask);
				}
			}
			catch (Exception ex)
			{
				CommUtil.AddSystemLog(7, 0, ex.Message);
			}
		}

		/// <summary>
		/// 每秒刷新一次状态
		/// </summary>
		/// <param name="source"></param>
		/// <param name="e"></param>
		private void RefrushCurrentVolmDic(object sender, EventArgs e)
		{
			bool checkResult = checkTaskCompleted();
			if(checkResult)
			{
				SimuTaskBegin1();
				Console.WriteLine("刷新一次状态");
			}
		}

		private void SimuTaskBegin()
		{
			// 获取后端计算结果
			SafeLoadAlgorithmService algorithmService = SafeLoadAlgorithmService.GetInstance();
			ManualCalcResult calcResult = algorithmService.CallAutoCalc(currentVolmDic, 3);
			//校验结果
			if (m_CurrentCalcResult.tankCalcStates.Count > 0)
			{
				// 生成任务列表
				TankTask task = ComposeTaskList(currentVolmDic, calcResult);
				simuTaskList = taskQueue.TaskService.GetAllWaitAndExecingAndCheckingTaskList();
				//如果当前任务列表里有正在执行的任务，则不再重复添加
				bool IsChecked = false;
				foreach (TankTask task0 in simuTaskList)
				{
					if (task0.TaskName == task.TaskName)
					{
						IsChecked = true;
						break;
					}
				}
				if (IsChecked == false)
				{
					//添加到任务列表
					simuTaskList.Add(task);
					//t_task添加到数据库
					taskQueue.TaskService.AddTask(task);
					CommUtil.AddSystemLog(6, 4, simuTaskList[0].TaskName);
				}
			}
			else
			{
				MessageBox.Show("后端生成的数据有误！");
			}
		}

		/// <summary>
		/// 启动模拟任务
		/// </summary>
		private void SimuTaskBegin1()
		{
			// 从数据库获取初始化任务列表
			simuTaskList = taskQueue.TaskService.GetAllWaitAndExecingAndCheckingTaskList();
			if (simuTaskList.Count() < 1)
			{
				// 获取后端计算结果
				SafeLoadAlgorithmService algorithmService = SafeLoadAlgorithmService.GetInstance();
				ManualCalcResult calcResult = algorithmService.CallAutoCalc(currentVolmDic, 3);
				//校验结果
				if (m_CurrentCalcResult.tankCalcStates.Count > 0)
				{
					// 生成任务列表
					TankTask task = ComposeTaskList(currentVolmDic, calcResult);
					if (task.TaskName.Length > 0)
					{
						//添加到任务列表
						simuTaskList.Add(task);
						//t_task添加到数据库
						taskQueue.TaskService.AddTask(task);
						CommUtil.AddSystemLog(6, 4, simuTaskList[0].TaskName);
						SimuTaskRunning();
					}
				}
				else
				{
					MessageBox.Show("后端生成的数据有误！");
				}
			}
		}

		/// <summary>
		/// 执行任务
		/// </summary>
		private void SimuTaskRunning()
        {
            for (int i = 0; i < simuTaskList.Count; i++)
            {
				//当任务状态为待执行时往下进行
				TankTask tmpTankTask = simuTaskList[i];
				if (tmpTankTask.TaskResult == TaskResultConstant.DEFAULT_ID)
                {
					//检查任务，并下发控制信号
					bool check = SimuTaskOpenValve();
					if (!check)
					{
						MessageBox.Show("存在异常任务");
						//将异常任务标注为执行失败
						tmpTankTask.TaskResult = TaskResultConstant.FAILED_ID;
					}
                }
            }
        }

        /// <summary>
        /// 检查当前任务是否已完成
        /// </summary>
        /// <param name="task"></param>
        private bool checkTaskCompleted()
        {
			bool check = false;
			foreach(int status in simuTankStatusList)
			{
				if(status != 0)
				{
					check = true;
					break;
				}
			}
			if (check)
			{
				SimuTaskCloseValve();
				return false;
			}
			else
			{
				if(simuTaskList.Count() > 0)
				{
					CommUtil.AddSystemLog(6, 5, simuTaskList[0].TaskName);
					simuTaskList.Clear();
				}
				simuTankList.Clear();
				simuTankLevelList.Clear();
				simuTankStatusList.Clear();
				simuTankValvesList.Clear();
				return true;
			}
		}

		//根据舱室动作生成设备开启模拟控制信号
		private bool SimuTaskOpenValve()
		{
			double check_value = 100.0;
			foreach (TankTask tankTask in simuTaskList)
			{
				simuTankList.Add(tankTask.TankId);
				simuTankLevelList.Add(tankTask.TargetVolm);
				simuTankStatusList.Add(tankTask.TaskType);

				foreach(WBTTask wbtTask in tankTask.WBTTaskList)
				{
					double initVolume = wbtTask.InitVolume;
					double targetVolume = wbtTask.TargetVolume;
					int isload = 1;
					if (targetVolume > initVolume + check_value) //压载
					{
						isload = 1;
					}
					else if (initVolume > targetVolume + check_value) //排载
					{
						isload = -1;
					}
					simuTankList.Add(wbtTask.WBTTankId);
					simuTankLevelList.Add(wbtTask.TargetVolume);
					simuTankStatusList.Add(isload);
				}
			}
			if (simuTankList.Count() > 0 && simuTankList.Count() == simuTankLevelList.Count())
			{
				//对对应舱室进行操作
				Dictionary<string, double> currentVolmDic0 = oilBallast.GetTankVolumeDic();
				for (int i = 0; i < simuTankList.Count(); i++)
				{
					string tankname = simuTankList[i];
					double targetLevel = simuTankLevelList[i];//计划液位高

					//double currentlevel = currentVolmDic0[tankname]; //当前液位高
					string statusname = string.Empty;
					if (tankname.IndexOf("CO") > -1)
					{
						if (simuTankStatusList[i] == 1)
						{
							statusname = "注入";
						}
						else if (simuTankStatusList[i] == -1)
						{
							statusname = "外输";
						}
					}
					else if (tankname.IndexOf("WB") > -1)
					{
						if (simuTankStatusList[i] == 1)
						{
							statusname = "压载";
						}
						else if (simuTankStatusList[i] == -1)
						{
							statusname = "排载";
						}
					}

					string searchname = string.Format("{0}_{1}", tankname, statusname);
					//启动调载过程
					foreach (OpcTask opcTask in taskList)
					{
						if (opcTask.TaskName == searchname)
						{
							List<string> valveList = new List<string>();
							List<OPCTag> closeCheckTags = new List<OPCTag>();
							Dictionary<string, object> openComDic = new Dictionary<string, object>();
							foreach (OPCTag tag in opcTask.TagList)
							{
								string status_tag = string.Format("{0}{1}", SysConfig.OPC_ADD_PRE, tag.OpcName);

								//NOTICE 实船使用这部分
								if (tag.OpcName.Contains("SCM_Open"))
								{
									openComDic.Add(status_tag, Convert.ToInt32(1));
									valveList.Add(tag.OpcName);
									continue;
								}
								else if(tag.OpcName.Contains("StatusClosed"))
									closeCheckTags.Add(tag);
							}
							simuTankValvesList.Add(valveList);
							//检查需关闭的设备是否按要求关闭，如有不符合要求的，则返回false
							try
							{
								opcUtil.GetOpcValues(closeCheckTags);
							}
							catch (Exception ex)
							{
								MessageBox.Show(ex.Message, "错误", MessageBoxButton.OK, MessageBoxImage.Error);
							}
							bool closeCheck = true;

							//这里为确保执行，暂时不检查其他舱室的阀门关闭情况
							//string closeCheckRes = "";
							//foreach (OPCTag tag in closeCheckTags)
							//{
							//	//DEBUG 这里需要确认下位机statusclosed的数据类型
							//	bool valStr = Convert.ToBoolean(tag.OpcValue.Value);
							//	if (valStr != true)
							//	{
							//		closeCheck = false;
							//	}
							//	closeCheckRes += string.Format("{0}:Value = {1}\n", tag.OpcName, tag.OpcValue.Value);
							//}
							//如果设备都按要求关闭，则可以下发开指令
							if (closeCheck)
							{
								try
								{
									opcUtil.SetOpcValues(openComDic);
									CommUtil.AddSystemLog(6, 2, searchname);
								}
								catch (Exception ex)
								{
									MessageBox.Show(ex.Message, "错误", MessageBoxButton.OK, MessageBoxImage.Error);
									return false;
								}
							}
							break;
						}
					}
				}
			}
			return true;
		}
		//根据舱室动作生成设备关闭模拟控制信号
		private void SimuTaskCloseValve()
		{
			Dictionary<string, double> currentVolmDic0 = oilBallast.GetTankVolumeDic();
			for (int i = 0; i < simuTankList.Count(); i++)
			{
				string tankname = simuTankList[i];
				double targetLevel = simuTankLevelList[i];
				int status = simuTankStatusList[i];
				if(status == 0)
					continue;
				double currentlevel = currentVolmDic0[tankname];
				if ((status == 1 && targetLevel <= currentlevel) || (status == -1 && targetLevel >= currentlevel))
				{
					//停止调载过程
					string statusname = string.Empty;
					if (tankname.IndexOf("CO") > -1)
					{
						if (simuTankStatusList[i] == 1)
						{
							statusname = "注入";
						}
						else if (simuTankStatusList[i] == -1)
						{
							statusname = "外输";
						}
					}
					else if (tankname.IndexOf("WB") > -1)
					{
						if (simuTankStatusList[i] == 1)
						{
							statusname = "压载";
						}
						else if (simuTankStatusList[i] == -1)
						{
							statusname = "排载";
						}
					}

					string searchname = string.Format("{0}_{1}", tankname, statusname);
					simuTankStatusList[i] = 0;
					//currentCheckValves为现在开启，但是即将关掉的设备，检查其是否关联其他任务，如关联，则暂不关闭
					List<string> currentCheckValves = simuTankValvesList[i];
					for (int m = 0; m < simuTankValvesList.Count(); m++)
					{
						int ongoing = simuTankStatusList[m];
						if (ongoing != 0)
						{
							List<string> tankValveList = simuTankValvesList[m];
							foreach (string valvename in tankValveList)
							{
								for(int j = currentCheckValves.Count()-1;j>=0;j--)
								{
									string target_valvename = currentCheckValves[j];
									if (valvename == target_valvename)
										currentCheckValves.Remove(target_valvename);
								}
							}
						}
					}
					if(currentCheckValves.Count() > 0)
					{
						Dictionary<string, object> closeComDic = new Dictionary<string, object>();
						foreach(string target_valvename in currentCheckValves)
						{
							string status_tag = string.Format("{0}{1}", SysConfig.OPC_ADD_PRE, target_valvename);
							
							string opcname0 = target_valvename.Replace("SCM_Open", "StatusOpened");
							status_tag = string.Format("{0}{1}", SysConfig.OPC_ADD_PRE, opcname0);
							closeComDic.Add(status_tag, 0);
							string opcname1 = target_valvename.Replace("SCM_Open", "StatusClosed");
							status_tag = string.Format("{0}{1}", SysConfig.OPC_ADD_PRE, opcname1);
							closeComDic.Add(status_tag, 1);
						}
						if (closeComDic.Count > 0)
						{
							try
							{
								opcUtil.SetOpcValues(closeComDic);
								CommUtil.AddSystemLog(6, 3, searchname);
							}
							catch (Exception ex)
							{
								MessageBox.Show(ex.Message, "错误", MessageBoxButton.OK, MessageBoxImage.Error);
							}
						}
					}
					break;
				}
			}
		}

        /// <summary>
        /// 根据当前状态以及后端计算结果生成任务列表
        /// </summary>
        /// <param name="currentVolmDic">当前状态</param>
        /// <param name="newResult">计算结果</param>
        private TankTask ComposeTaskList(Dictionary<string, double> currentVolmDic, ManualCalcResult calcResult)
        {
			//这里先单独建一个货油舱计划，压载舱计划作为子成员单独加入
			//这里需要判断货油舱的状态
			double check_value = 100.0;
			double default_timespan = 2.0; //hrs
			TankTask task = new TankTask();
			foreach (TankCalcState tank in calcResult.tankCalcStates)
            {
				string abname = tank.Abname;
				//先判断舱室是否在可调载舱室列表内
				double initVolume = 0;
				try
				{
					initVolume = currentVolmDic[abname];
				}
				catch (Exception ex)
				{
					continue;
				}

				if (abname.IndexOf("CO") > -1)
				{
					//判断任务类型，如果舱室没有动作，则跳过
					if (tank.Volume > initVolume + check_value)
					{
						//先在数据库里找对应的任务，如果有则更新
						//装载
						task.TaskType = 1; //任务类型
					}
					//NOTICE 暂时不考虑货油舱卸载的情况
					//else if (initVolume > tank.Volume + check_value)
					//{
					//	//卸载
					//	task.TaskType = -1;
					//}
					else
					{
						//不动
						continue;
					}
					if (task.TaskType == 1)
					{
						task.TaskName = string.Format("{0}_{1}", tank.Abname, "注入");
					}
					else if (task.TaskType == -1)
					{
						task.TaskName = string.Format("{0}_{1}", tank.Abname, "外输");
					}

					double tank_maxVolm = TankConstant.GetTankVolume(abname);
					double initfill = initVolume / tank_maxVolm * 100;

					task.TaskId = simuTaskList.Count + 1;//任务id
					task.TaskQueueId = 1;//队列id
					task.TankId = tank.Abname;//舱室名称
					task.TargetVolm = tank.Full;//目标容量百分比
					task.InitVolm = initfill;
					task.PipeSpeed = 0;//流速
					task.TaskState = TaskStateConstant.WATING_ID;//默认设置为等待执行，跳过确认
					task.TaskResult = TaskResultConstant.DEFAULT_ID;

					//这里PlanStartTime开始时间都是DateTime.Now
					TankTask preTask = taskTankCalcService.getPreTask(1);
					if (preTask != null)
					{
						task.PreTaskId = preTask.TaskId;
						task.StartType = TaskStartTypeConstant.START_BY_QUEUE_ID;
						task.PlanStartTime = DateTime.Now;
					}
					else
					{
						task.PreTaskId = 0;
						task.StartType = TaskStartTypeConstant.START_BY_TIME_ID;
						task.PlanStartTime = DateTime.Now;
					}
					task.PlanStartTime = DateTime.Now;
					task.PlanEndTime = DateTime.Now.AddHours(default_timespan);
					task.ExecStartTime = DateTime.Now;
					task.ExecEndTime = DateTime.Now.AddHours(default_timespan);
					task.SwapTargetTank1 = "0";
					task.CreateTime = DateTime.Now;
					task.UpdateTime = DateTime.Now;
					task.DeleteTime = DateTime.Now;
				}
				else
				{
					//判断任务类型，如果舱室没有动作，则跳过
					if(task.TaskName.Length > 0)
					{
						bool isload = false;
						if (tank.Volume > initVolume + check_value) //压载
						{
							isload = true;
						}
						else if (initVolume > tank.Volume + check_value) //排载
						{
							isload = true;
						}
						else //不动
						{
							continue;
						}

						double tank_maxVolm = TankConstant.GetTankVolume(abname);
						double initfill = initVolume / tank_maxVolm * 100;

						task.WBTTaskList.Add(new WBTTask()
						{
							WBTTankId = abname,
							PipeSpeed = 0,
							TargetVolume = tank.Full,
							InitVolume = initVolume,
							IsLoad = isload
						});
					}
				}
            }
			task.WBTDetail = JsonConvert.SerializeObject(task.WBTTaskList);
			return task;
		}

		//下面是根据实采数据刷新对应数组的函数
		private void UpdateOpcValues_TankStatus(List<OPCTag> tmpTagList)
		{
			if (tmpTagList != null && tmpTagList.Count > 0)
			{
				opcUtil.GetOpcValues(tmpTagList);
			}
		}
		private void UpdateOpcValues_ValveStatus(List<OPCTag> tmpTagList)
		{
			if (tmpTagList != null && tmpTagList.Count > 0)
			{
				opcUtil.GetOpcValues(tmpTagList);
			}
		}
		private void UpdateOpcValues_PumpStatus(List<OPCTag> tmpTagList)
		{
			if (tmpTagList != null && tmpTagList.Count > 0)
			{
				opcUtil.GetOpcValues(tmpTagList);
			}
		}
		private void UpdateOpcValues_HardwireStatus(List<OPCTag> tmpTagList)
		{
			if (tmpTagList != null && tmpTagList.Count > 0)
			{
				opcUtil.GetOpcValues(tmpTagList);
			}
		}
		private void UpdateOpcValues_FlammableGasStatus(List<OPCTag> tmpTagList)
		{
			if (tmpTagList != null && tmpTagList.Count > 0)
			{
				opcUtil.GetOpcValues(tmpTagList);
			}
		}
	}
}
